package com.bicon.botu.mall.base.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bicon.botu.mall.base.common.BaseConstants;
import com.bicon.botu.mall.base.common.ValidationUtil;
import com.bicon.botu.mall.base.dto.DictionaryDTO;
import com.bicon.botu.mall.base.dto.DictionaryNodeDTO;
import com.bicon.botu.mall.base.dto.KeyValueDTO;
import com.bicon.botu.mall.base.entity.Dictionary;
import com.bicon.botu.mall.base.entity.MallConfig;
import com.bicon.botu.mall.base.service.IMallConfigService;
import com.bicon.botu.core.base.bean.GlobalRedisTemplate;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.utils.BeanMapper;
import com.bicon.botu.core.base.common.utils.NodeUtil;
import com.bicon.botu.core.base.common.utils.StringUtils;
import com.bicon.botu.core.base.repository.redis.RedisHandler;
import com.bicon.botu.mall.base.mapper.DictionaryMapper;
import com.bicon.botu.mall.base.service.IDictionaryService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 存放常用配置参数、地区、年龄段、性别、指标类型等数据 服务实现类
 * </p>
 *
 * @author tandk
 * @since 2017-07-31
 */
@Service
public class DictionaryServiceImpl extends ServiceImpl<DictionaryMapper, com.bicon.botu.mall.base.entity.Dictionary> implements IDictionaryService {

    @Autowired
    RedisHandler redisHandler;

    @Autowired
    private GlobalRedisTemplate globalRedisTemplate;

    @Autowired
    IMallConfigService mallConfigService;
    /**
     * 初始化字典缓存
     *
     * @return
     */
    @Override
    public boolean initDictionaryRedis() {
        List<Dictionary> keyValueDictList = new Dictionary().selectList(new EntityWrapper().eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        Map<String, String> map = new HashMap<>(16);
        keyValueDictList.stream().forEach(dictionary -> map.put(Integer.toString(dictionary.getId()), dictionary.getDictionaryName()));
        boolean result = redisHandler.getGlobalRedisTemplate().remove(BaseConstants.BOTU_MALL_DICTIONARY, "");
        if (!result) {
            return result;
        }
        result = redisHandler.getGlobalRedisTemplate().cacheHashAll(BaseConstants.BOTU_MALL_DICTIONARY, "", map);
        return result;
    }

    /**
     * 初始化基础字典缓存
     *
     * @return
     */
    @Override
    public boolean initBaseDictionaryRedis() {
        Dictionary dictionary = new Dictionary();
        // 写入Key Value型（type为1的配置）配置
        List<Dictionary> keyValueDictList = dictionary.selectList(new EntityWrapper().eq("type", "1").notIn("logic_delete", Constants.DEL_LOGIC_DELETE));

        this.globalRedisTemplate.delete(BaseConstants.BOTU_MALL_DICTIONARY_BASE_CONFIG);

        this.globalRedisTemplate.executePipelined(new RedisCallback<List<String>>() {
            @Override
            public List<String> doInRedis(RedisConnection connection) throws DataAccessException {
                for (int i = 0; i < keyValueDictList.size(); i++) {
                    connection.hSet(globalRedisTemplate.getKeySerializer().serialize(BaseConstants.BOTU_MALL_DICTIONARY_BASE_CONFIG),
                            globalRedisTemplate.getKeySerializer().serialize(keyValueDictList.get(i).getDictionaryCode()),
                            globalRedisTemplate.getKeySerializer().serialize(keyValueDictList.get(i).getContent()));
                }
                return null;
            }
        });

        // 删除旧缓存
        Set<String> hashKeySet = this.globalRedisTemplate.keys(BaseConstants.BOTU_MALL_DICTIONARY_HASH_CONFIG + ":*");
        this.globalRedisTemplate.delete(hashKeySet);

        // 写入List型配置（type为2的配置）
        List<Dictionary> hashDictList = dictionary.selectList(new EntityWrapper().eq("type", "2").notIn("logic_delete", Constants.DEL_LOGIC_DELETE).orderBy("dictionary.parent_id",true).orderBy("dictionary.order",true));
        Map<String, Map<String, Dictionary>> hashDictMap = this.parseHashDict(hashDictList);
        this.globalRedisTemplate.executePipelined(new RedisCallback<List<String>>() {
            @Override
            public List<String> doInRedis(RedisConnection connection) throws DataAccessException {
                Iterator<String> keyIterator = hashDictMap.keySet().iterator();
                while (keyIterator.hasNext()) {
                    String key = keyIterator.next();
                    Map<String, Dictionary> subMap = hashDictMap.get(key);
                    //
                    if (subMap.size() > 0) {
                        Iterator<String> subIterator = subMap.keySet().iterator();
                        Map<byte[], byte[]> byteMap = new HashMap<>();
                        while (subIterator.hasNext()) {
                            String subKey = subIterator.next();
                            byteMap.put(globalRedisTemplate.getKeySerializer().serialize(subKey), globalRedisTemplate.getValueSerializer().serialize(JSON.toJSONString(subMap.get(subKey))));
                        }
                        connection.hMSet(globalRedisTemplate.getKeySerializer().serialize(BaseConstants.BOTU_MALL_DICTIONARY_HASH_CONFIG + ":" + key), byteMap);
                    }
                }
                return null;
            }
        });

        return true;
    }


    /**
     * 新增字典
     *
     * @param dictionary
     * @return
     */
    @Override
    public boolean addDictionary(Dictionary dictionary) {
        boolean b = insert(dictionary);
        if (b) {
            // 更新字典path
            dictionary.setPath(dictionary.getPath() + (StringUtils.isNotEmpty(dictionary.getPath()) ? ":" : "") + dictionary.getId());
            b = dictionary.updateById();
            b = this.cacheDictionary(dictionary);
            //保存至缓存
            redisHandler.getGlobalRedisTemplate()
                    .cacheHash(BaseConstants.BOTU_MALL_DICTIONARY, "", Integer.toString(dictionary.getId()), dictionary.getDictionaryName());
        }
        return b;
    }

    /**
     * 删除字典
     *
     * @param id
     * @return
     */
    @Override
    public boolean delDictionary(int id) {
        Dictionary dictionary = new Dictionary();
        dictionary.setId(id);
        dictionary = dictionary.selectById();
        boolean b = dictionary.deleteById();
        this.removeDictionary(dictionary);
        b = redisHandler.getGlobalRedisTemplate().removeHash(BaseConstants.BOTU_MALL_DICTIONARY, "", Integer.toString(dictionary.getId()));
        return b;
    }

    /**
     * 修改字典
     *
     * @param dictionary
     * @return
     */
    @Override
    public boolean updateDictionary(Dictionary dictionary) {
        Dictionary oldDict = dictionary.selectById();
        boolean b = dictionary.updateById();
        this.removeDictionary(oldDict);
        b = this.cacheDictionary(dictionary);
        //保存至缓存
        b = redisHandler.getGlobalRedisTemplate()
                .cacheHash(BaseConstants.BOTU_MALL_DICTIONARY, "", Integer.toString(dictionary.getId()), dictionary.getDictionaryName());
        return b;
    }


    /**
     * 根据父字典code获取字典集合
     *
     * @param code 父字典code
     * @return 子字典集合
     */
    @Override
    public List<Dictionary> findListByParentCode(String code) {
        Dictionary dictionary = new Dictionary().selectOne(new EntityWrapper().eq("dictionary_code", code).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        List<String> dictJsonList = this.globalRedisTemplate.opsForHash().values(BaseConstants.BOTU_MALL_DICTIONARY_HASH_CONFIG + ":" + code);
        List<Dictionary> result = new ArrayList<Dictionary>();
        for (String dictJson : dictJsonList) {
            result.add(JSON.parseObject(dictJson, Dictionary.class));
        }
        return result;
    }

    /**
     * 根据父id获取字典集合
     *
     * @param parentId 父id
     * @return 子字典集合
     */
    @Override
    public List<DictionaryNodeDTO> findAllDictionaryNode(Integer parentId, String code) {
        if (parentId != null && parentId >= 0) {
            List<Dictionary> dictionaryList = new Dictionary().selectList(new EntityWrapper().like("path", parentId + ":", SqlLike.RIGHT));
            List<DictionaryNodeDTO> dictionaryDTOList = BeanMapper.mapList(dictionaryList, DictionaryNodeDTO.class);
            return new NodeUtil<DictionaryNodeDTO>().getChildNodes(dictionaryDTOList, parentId + "");
        } else if (StringUtils.isNotEmpty(code)) {
            //获取此code对应的字典
            Dictionary dictionary = new Dictionary().selectOne(new EntityWrapper().eq("dictionary_code", code));
            //获取此code对应的字典及子字典集合
            List<Dictionary> dictionaryList = new Dictionary().selectList(new EntityWrapper().eq("path", dictionary.getId() + "").or().like("path", dictionary.getId() + ":", SqlLike.RIGHT));
            List<DictionaryNodeDTO> dictionaryDTOList = BeanMapper.mapList(dictionaryList, DictionaryNodeDTO.class);
            return new NodeUtil<DictionaryNodeDTO>().getChildNodes(dictionaryDTOList, dictionary.getId() + "");
        }
        return null;
    }


    /**
     * 根据id查询字典
     *
     * @return 字典
     */
    @Override
    public KeyValueDTO<String> findDictionaryFromRedis(String id) {
        String result = redisHandler.getGlobalRedisTemplate().getHash(BaseConstants.BOTU_MALL_DICTIONARY, "", id);
        return JSONObject.parseObject(result, KeyValueDTO.class);
    }


    /**
     * 将Hash型的配置转换成Map<String,Map<String,Dictionary>> 结构，用于redis存储。
     *
     * @param hashDictList type为2的Dictionary对象
     * @return
     */
    private Map<String, Map<String, Dictionary>> parseHashDict(List<Dictionary> hashDictList) {
        if (CollectionUtils.isEmpty(hashDictList)) {
            return null;
        }
        Map<String, Map<String, Dictionary>> result = new HashMap<String, Map<String, Dictionary>>();

        for (int i = 0; i < hashDictList.size(); i++) {
            Dictionary dict = hashDictList.get(i);
            String parentCode = "";
            //获取dict的父code。
            if (dict.getParentId() != 0) {
                for (int j = 0; j < hashDictList.size(); j++) {
                    if (hashDictList.get(j).getId() == dict.getParentId()) {
                        parentCode = hashDictList.get(j).getDictionaryCode();
                    }
                }
            }

            if (StringUtils.isNotEmpty(parentCode)) {
                Map<String, Dictionary> dictMap = result.get(parentCode);
                if (dictMap == null) {
                    dictMap = new HashMap<String, Dictionary>();
                    result.put(parentCode, dictMap);
                }
                dictMap.put(String.valueOf(dict.getId()), dict);
            } else {
                result.put(dict.getDictionaryCode(), new HashMap<String, Dictionary>());
            }
        }
        return result;
    }

    /**
     * 设置类型为1和2的字典缓存
     *
     * @param dictionary 字典
     * @return
     */
    private boolean cacheDictionary(Dictionary dictionary) {
        if (dictionary.getType() == 1) {
            redisHandler.getGlobalRedisTemplate().cacheHash(BaseConstants.BOTU_MALL_DICTIONARY_BASE_CONFIG, "", dictionary.getDictionaryCode(), dictionary.getContent());
        } else if (dictionary.getType() == 2) {
            if (dictionary.getParentId() > 0) {
                Dictionary parent = dictionary.selectById(dictionary.getParentId());
                parent.getDictionaryCode();
                //新增到redis中
                redisHandler.getGlobalRedisTemplate().cacheHash(BaseConstants.BOTU_MALL_DICTIONARY_HASH_CONFIG, ":" + parent.getDictionaryCode(),
                        String.valueOf(dictionary.getId()), JSON.toJSONString(dictionary));
            }
        }
        return true;
    }

    private boolean removeDictionary(Dictionary dictionary) {
        if (dictionary.getType() == 1) {
            redisHandler.getGlobalRedisTemplate().removeHash(BaseConstants.BOTU_MALL_DICTIONARY_BASE_CONFIG, "", dictionary.getDictionaryCode());
        } else {
            if (dictionary.getParentId() != 0) {
                Dictionary parent = dictionary.selectById(dictionary.getParentId());
                redisHandler.getGlobalRedisTemplate().removeHash(BaseConstants.BOTU_MALL_DICTIONARY_HASH_CONFIG, ":" + parent.getDictionaryCode(), String.valueOf(dictionary.getId()));
            } else {
                redisHandler.getLocalRedisTemplate().remove(BaseConstants.BOTU_MALL_DICTIONARY_HASH_CONFIG, ":" + dictionary.getDictionaryCode());
            }

        }

        return true;
    }

    /**
     * 获取所有订单相关的配置项列表
     * @return
     */
    @Override
    public Map<String, Object> getOrderConfig(String code) {
        Map<String, Object> map = new HashedMap();
         //获取所有订单相关的配置项列表
        //获取type 为2的字典列表
        Dictionary dictionary = new Dictionary().selectOne(new EntityWrapper<Dictionary>().eq("dictionary_code", code).eq("logic_delete", Constants.DEL_LOGIC_NORMAL));
        EntityWrapper<Dictionary> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("parent_id", dictionary.getId());
        //过滤不等于1的2级
        entityWrapper.notIn("logic_delete", Constants.DEL_LOGIC_DELETE);
        entityWrapper.orderBy("dictionary.order");
        List<Dictionary> list = dictionary.selectList(entityWrapper);

        List<Dictionary> list1 = new ArrayList<>();
        List<Dictionary> list2 = new ArrayList<>();
        for(Dictionary dictionary1 : list){
            if(ValidationUtil.equals(dictionary1.getType(),2)){
                list1.add(dictionary1);
            }else{
                list2.add(dictionary1);
            }
        }
        //配置2列表
        List<DictionaryDTO> orderConfigList1 = BeanMapper.mapList(list1, DictionaryDTO.class);
        //缓存获取对象
        for(DictionaryDTO dictionaryDTO : orderConfigList1){
            //父级code
            List<String> dictJsonList = this.globalRedisTemplate.opsForHash().values(BaseConstants.BOTU_MALL_DICTIONARY_HASH_CONFIG + ":" + dictionaryDTO.getDictionaryCode());
            List<DictionaryDTO> result = new ArrayList<DictionaryDTO>();
            for (String dictJson : dictJsonList) {
                result.add(JSON.parseObject(dictJson, DictionaryDTO.class));
            }
            dictionaryDTO.setDictionaryDTOList(getSortList(result));
        }
        //配置1列表
        List<DictionaryDTO> orderConfigList = BeanMapper.mapList(list2, DictionaryDTO.class);
        //查询所有的配置1的值
        List<MallConfig> mallConfigs = new ArrayList<>();
        EntityWrapper<MallConfig> mallConfigEntityWrapper = new EntityWrapper<>();
        mallConfigs = mallConfigService.selectList(mallConfigEntityWrapper);
        if(!ValidationUtil.isEmpty(mallConfigs)){
            //通过配置的list code找值
            for(DictionaryDTO dictionaryDTO :orderConfigList){
                for (MallConfig mallConfig:mallConfigs){
                    if(ValidationUtil.equals(dictionaryDTO.getDictionaryCode(),mallConfig.getDictionaryCode())){
                        List<DictionaryDTO> orderConfigList11 = new ArrayList<>();
                        DictionaryDTO dictionaryDTO1 = new DictionaryDTO();
                        dictionaryDTO1.setDictionaryCode(mallConfig.getDictionaryValue());
                        dictionaryDTO1.setDictionaryName(mallConfig.getDictionaryCode());
                        orderConfigList11.add(dictionaryDTO1);
                        dictionaryDTO.setDictionaryDTOList(orderConfigList11);
                        break;
                    }
                }
            }
        }

        map.put("orderConfigList",orderConfigList);
        map.put("orderConfigList1",orderConfigList1);
        return map;
    }

    public static List<DictionaryDTO> getSortList(List<DictionaryDTO> list){
//        Collections.sort(list, (DictionaryDTO o1, DictionaryDTO o2) -> o1.getOrder() > o2.getOrder() ? 1:-1);
        Collections.sort(list, new Comparator<DictionaryDTO>() {
            @Override
            public int compare(DictionaryDTO o1, DictionaryDTO o2) {
                if(o1.getOrder()>o2.getOrder()){
                    return 1;
                }
                if(o1.getOrder().equals(o2.getOrder())){
                    return 0;
                }
                return -1;
            }
        });
        return list;
    }
}
